package com.aiti.lulian.service.impl;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.aiti.base.core.utils.message.Message;
import com.aiti.lulian.dto.ShowActivityInfoDto;
import com.aiti.lulian.entity.ShowActivityInfo;
import com.aiti.lulian.entity.SysArea;
import com.aiti.lulian.gxmh.util.JsoupUtils;
import com.aiti.lulian.mapper.ShowActivityInfoMapper;
import com.aiti.lulian.mapper.SysAreaMapper;
import com.aiti.lulian.service.SearchService;
import com.aiti.lulian.service.ShowActivityInfoService;
import com.aiti.lulian.utils.HttpClientUtil;
import com.aiti.lulian.vo.ShowActivityInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * <p>
 * 活动 服务实现类
 * </p>
 *
 * @author 
 * @since 2025-06-11
 */
@Service
@Slf4j
public class ShowActivityInfoServiceImpl extends ServiceImpl<ShowActivityInfoMapper, ShowActivityInfo> implements ShowActivityInfoService {
    private static final String HOST = "https://www.onezh.com";

    private static final String INTERNAL_ACTIVITY_LIST = "/zhanhui/%s_0_0_0_%s/%s/";

    private static final String ABROAD_ACTIVITY_LIST = "/haiwai/%s_0_0_0_%s/%s/";

    private static final DateTimeFormatter INPUT_FORMAT = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
    private static final DateTimeFormatter OUTPUT_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd");



    @Autowired
    private ShowActivityInfoMapper activityMapper;

    @Autowired
    private SearchService searchService;

    @Autowired
    private SysAreaMapper sysAreaMapper;




    // 从页面解析总页数
    private static int parseTotalPages(Document doc) {
        // 查找包含总页数的元素（如：共810页）
        Element pageInfo = doc.selectFirst("div.NewPage span:contains(共)");
        if (pageInfo != null) {
            String text = pageInfo.text();
            // 使用正则表达式提取数字
            Matcher matcher = Pattern.compile("共(\\d+)页").matcher(text);
            if (matcher.find()) {
                return Integer.parseInt(matcher.group(1));
            }
        }

        // 备用方案：查找分页区域的最大页码
        Elements pageLinks = doc.select("div.NewPage a[href]");
        int maxPage = 1;
        for (Element link : pageLinks) {
            String href = link.attr("href");
            Matcher m = Pattern.compile("/zhanhui/(\\d+)_").matcher(href);
            if (m.find()) {
                int pageNum = Integer.parseInt(m.group(1));
                if (pageNum > maxPage) maxPage = pageNum;
            }
        }
        return maxPage;
    }

    public static ShowActivityInfo parseInternalExhibitionDetail(String url) throws IOException {
        Document doc = HttpClientUtil.getDocumentFromURL(url);

        ShowActivityInfo activityInfo = new ShowActivityInfo();
        activityInfo.setFirstActivityType("国内活动");
        activityInfo.setSecondActivityType("行业展会");
        activityInfo.setStartEnrollFlag(true);

        // 1. 提取展会名称
        Element titleElement = doc.selectFirst("#tuan-title");
        if (titleElement != null) {
            activityInfo.setBaseName(titleElement.text().trim());
        }

        // 2. 提取展会时间
        Elements timeElements = doc.select("dl.tuan-info:has(dt.tuan-name:contains(展会时间)) dd .bao-key");
        if (!timeElements.isEmpty()) {
            String timeText = timeElements.first().ownText();
            // 清理文本并提取日期部分
            timeText = timeText.replaceAll("&nbsp;", " ").replaceAll("纠错", "").trim();

            // 使用正则提取日期范围
            Pattern pattern = Pattern.compile("(\\d{4}年\\d{1,2}月\\d{1,2}日)[—\\-至](\\d{1,2}月\\d{1,2}日)");
            Matcher matcher = pattern.matcher(timeText);

            String startDateStr = matcher.group(1);
            // 处理结束日期（可能没有年份）
            String endDatePart = matcher.group(2);
            String endDateStr = startDateStr.substring(0, 5) + endDatePart;

            LocalDate startDate = LocalDate.parse(startDateStr, INPUT_FORMAT);
            LocalDate endDate = LocalDate.parse(endDateStr, INPUT_FORMAT);

            activityInfo.setBeginTime(new Date(startDate.format(OUTPUT_FORMAT)));
            activityInfo.setEndTime(new Date(endDate.format(OUTPUT_FORMAT)));
        }

        // 3. 提取展会地点
        Elements locationElements = doc.select("dl.tuan-info:has(dt.tuan-name:contains(展会地点)) dd .bao-key");
        if (!locationElements.isEmpty()) {
            // 提取纯文本（去除HTML标签）
            String location = locationElements.first().text()
                    .replace("乘车路线", "")
                    .replaceAll("\\s+", " ")
                    .trim();
            activityInfo.setAddress(location);
        }

        // 4. 提取展会介绍
        Element introSection = doc.selectFirst("p.zhxx:contains(展会介绍)");
        if (introSection != null) {
            Element introElement = introSection.nextElementSibling();
            if (introElement != null && introElement.hasClass("article")) {
                // 清理介绍文本
                String introduction = introElement.text()
                        .replaceAll("\\s+", " ")
                        .replaceAll("^展会介绍\\s*", "")
                        .trim();
                activityInfo.setDescription(introduction);
            }
        }

        Element imgElement = doc.select("img.zhlogo").first(); // 使用类名 zhlogo 精确匹配
        if (imgElement != null) {
            String imgUrl = imgElement.attr("abs:src"); // 获取绝对路径
            System.out.println("图片链接：" + imgUrl);
            activityInfo.setPic(imgUrl);
        }

        Element picList = doc.selectFirst("ul.picList");
        List<String> picUrlList = new ArrayList<>();
        if (picList != null) {
            // 获取所有 a 标签
            Elements links = picList.select("a[href]");

            for (Element link : links) {
                String href = link.attr("abs:href"); // 绝对路径
                Element img = link.selectFirst("img");

                String imgSrc = "";
                String dataOriginal = "";

                if (img != null) {
                    imgSrc = img.absUrl("src");
                    dataOriginal = img.hasAttr("data-original") ? img.attr("abs:data-original") : "";
                }

                System.out.println("链接地址：" + href);
                System.out.println("图片地址：" + imgSrc);
                if (!dataOriginal.isEmpty()) {
                    System.out.println("高清原图地址：" + dataOriginal);
                }
                picUrlList.add(dataOriginal);
                System.out.println("----------------------------");
            }
        } else {
            System.out.println("未找到 picList 元素");
        }
        if(!CollectionUtils.isEmpty(picUrlList)){
            String picUrls = picUrlList.stream()
                    .filter(u -> u != null && !u.trim().isEmpty())
                    .collect(Collectors.joining(","));
            activityInfo.setDetailPic(picUrls);
        }

        System.out.println("提取的详情结果："+activityInfo);
        return activityInfo;
    }


    @Override
    public Message internalAddActivity() {
        List<String> internalErrorList = new ArrayList<>();
        List<String> internalList = new ArrayList<>();
        List<String> abroadList = new ArrayList<>();
        Document firstPage = HttpClientUtil.getDocumentFromURL(HOST + String.format(INTERNAL_ACTIVITY_LIST, "1", "0", "0"));
        // 提取当前页的所有详情链接
        Elements blocks = firstPage.select("div.jxs_list > div.row");
        for (Element block : blocks) {
            Element link = block.selectFirst("a[href^=/web/index_]");
            if (link != null) {
                String detailUrl = link.attr("href");
                internalList.add(HOST + detailUrl);
            }
        }
        // 解析总页数
        int totalPages = parseTotalPages(firstPage);
        System.out.println("总页数: " + totalPages);

        // 2. 处理每一页
//        for (int page = 2; page <= totalPages; page++) {
//            System.out.println("正在处理第 " + page + " 页...");
//
//            // 构建当前页URL
////            String pageUrl = BASE_URL + "/zhanhui/" + page + "_0_0_0_0/0/";
//            String url = HOST + String.format(INTERNAL_ACTIVITY_LIST, String.valueOf(page), "0", "0");
//
//            Document doc;
//            doc = HttpClientUtil.getDocumentFromURL(url);
//
//            // 3. 提取当前页的所有详情链接
//            Elements exhibitionBlocks = doc.select("div.jxs_list > div.row");
//            for (Element block : exhibitionBlocks) {
//                Element link = block.selectFirst("a[href^=/web/index_]");
//                if (link != null) {
//                    String detailUrl = link.attr("href");
//                    internalList.add(HOST + detailUrl);
//                }
//            }
//            System.out.println("最终结果："+internalList);
//
//            // 添加延迟避免请求过快
//            try{
//                Thread.sleep(3000);
//            }catch (Exception e){
//
//            }
//
//        }

        // 4. 输出结果
        System.out.println("\n共找到 " + internalList.size() + " 个详情页:");
        List<ShowActivityInfo> internalResultList = new ArrayList();
        for (String link : internalList) {
            System.out.println(link);
            try{
                ShowActivityInfo activityInfo = parseInternalExhibitionDetail(link);
                internalResultList.add(activityInfo);
            }catch(Exception e){
                log.error("获取html文档失败：{}", ExceptionUtil.stacktraceToString(e));
                internalErrorList.add(link);
                continue;
            }

        }
        if(CollectionUtils.isEmpty(internalErrorList)){
            return Message.success(internalResultList);
        }else{
            return Message.fail(internalErrorList);
        }

    }

    @Override
    public Message abroadAddActivity() {
        Set<String> allLinks = new HashSet<>();
        ArrayList<ShowActivityInfo> activityInfolist = new ArrayList<>();
        try {
            List<String> abroadErrorList = new ArrayList<>();
            // 解析初始HTML
            Document doc = HttpClientUtil.getDocumentFromURL(HOST + String.format(ABROAD_ACTIVITY_LIST, "1", "0", "0"));

            // 1. 获取最大页数
            int maxPage = extractMaxPage(doc);
            System.out.println("最大页数: " + maxPage);

            // 2. 提取所有页面的链接


            // 处理第一页
            allLinks.addAll(extractPageLinks(doc));

            // 处理后续页面
//            for (int page = 2; page <= maxPage; page++) {
//                //String pageUrl = constructPageUrl(doc, page);
//                String url = HOST + String.format(ABROAD_ACTIVITY_LIST, String.valueOf(page), "0", "0");
//                System.out.println("请求页面: " + url);
//
//                Document pageDoc = HttpClientUtil.getDocumentFromURL(url);
//                allLinks.addAll(extractPageLinks(pageDoc));
//            }

            // 输出所有链接
            System.out.println("\n提取的所有链接:");
            for (String link : allLinks) {
                System.out.println(link);
                try{
                    Document detailDocument = HttpClientUtil.getDocumentFromURL(link);
                    ShowActivityInfo showActivityInfo = parseAbroadExhibitionDetail(detailDocument);
                    activityInfolist.add(showActivityInfo);
                    Thread.sleep(3000);
                }catch(Exception e){
                    log.error("获取html文档失败：{}", ExceptionUtil.stacktraceToString(e));
                    abroadErrorList.add(link);
                    continue;
                }



            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return Message.success(activityInfolist);
    }

    @Override
    public List<ShowActivityInfoVo> listActivities(Page page, ShowActivityInfoDto dto) {
        List<ShowActivityInfoVo> showActivityInfoVos = activityMapper.listActivities(page, dto);
        return showActivityInfoVos;
    }

    @Override
    public ShowActivityInfo getActivityById(String id) {
        ShowActivityInfo activityInfo = this.getById(id);
        return activityInfo;
    }

    @Override
    public Message saveActivity(ShowActivityInfo activity) {
        this.save(activity);
        return Message.success();
    }

    @Override
    public Message updateActivity(ShowActivityInfo activity) {
        this.updateById(activity);
        return Message.success();
    }

    @Override
    public Message deleteActivity(String id) {
        this.removeById(id);
        return Message.success();
    }

    @Override
    public Message internalAddEShow365Activity() {
        LambdaQueryWrapper<ShowActivityInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(ShowActivityInfo::getBeginTime).eq(ShowActivityInfo::getSource,"1")
                .eq(ShowActivityInfo::getFirstActivityType, "国内活动")
                .eq(ShowActivityInfo::getSecondActivityType, "行业展会")
                .orderByDesc(ShowActivityInfo::getBeginTime);
        List<ShowActivityInfo> list = this.list(wrapper);
        Date today = new Date();
//        if(!CollectionUtils.isEmpty(list)){
//            today = list.get(0).getBeginTime();
//        }
        List<ShowActivityInfo> showActivityInfos = searchService.addInternalActivity(today);
        if(!CollectionUtils.isEmpty(showActivityInfos)){
            this.saveBatch(showActivityInfos);
        }



        return Message.success();
    }

    @Override
    public Message abroadAddEShow365Activity() {
        LambdaQueryWrapper<ShowActivityInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(ShowActivityInfo::getBeginTime).eq(ShowActivityInfo::getSource,"1")
                .eq(ShowActivityInfo::getFirstActivityType, "海外活动")
                .eq(ShowActivityInfo::getSecondActivityType, "海外展会")
                .orderByDesc(ShowActivityInfo::getBeginTime);
        List<ShowActivityInfo> list = this.list(wrapper);
        Date today = new Date();
        if(!CollectionUtils.isEmpty(list)){
            today = list.get(0).getBeginTime();
        }
        List<ShowActivityInfo> showActivityInfos = searchService.addAbroadActivity(today);
        if(!CollectionUtils.isEmpty(showActivityInfos)){
            this.saveBatch(showActivityInfos);
        }



        return Message.success();
    }


    private static int extractMaxPage(Document doc) {
        Element pageInfo = doc.selectFirst("span.Total");
        if (pageInfo != null) {
            String text = pageInfo.text();
            return Integer.parseInt(text.replaceAll("\\D+", ""));
        }
        return 1; // 如果没有找到分页信息，默认为1页
    }

    // 构造分页URL
    private static String constructPageUrl(Document doc, int page) {
        // 查找当前页面URL模式
        Elements pageLinks = doc.select("div.Page a[href]");
        if (!pageLinks.isEmpty()) {
            String href = pageLinks.first().attr("href");
            return href.replaceAll("/\\d+_", "/" + page + "_");
        }
        return ""; // 回退方案
    }

    // 提取单个页面的所有链接
    private static Set<String> extractPageLinks(Document doc) {
        Set<String> links = new HashSet<>();
        Element listContainer = doc.selectFirst("div.jxs_list");

        if (listContainer != null) {
            Elements linkElements = listContainer.select("a[href]");
            for (Element link : linkElements) {
                String href = link.attr("href");
                // 过滤有效链接
                if (href.startsWith("/haiwai/index_") && href.endsWith(".html")) {
                    links.add(HOST + href);
                }
            }
        }
        return links;
    }

    public ShowActivityInfo parseAbroadExhibitionDetail(Document doc) {

        ShowActivityInfo activityInfo = new ShowActivityInfo();

        // 1. 提取展会标题
        String title = doc.selectFirst("div.tuan-detail.wrap h1.tuan-title").text().trim();
        activityInfo.setBaseName(title);

        // 2. 提取并处理展会时间
        String dateText = "";
        Elements infoItems = doc.select("dl.tuan-info");
        for (Element item : infoItems) {
            if (item.selectFirst("dt.tuan-name").text().equals("展会时间：")) {
                dateText = item.select("div.bao-key").first().ownText().replaceAll("\\s+", "");
                break;
            }
        }
        String[] dateParts = parseExhibitionDates(dateText);
        if(dateParts.length == 2){
            activityInfo.setBeginTime(new Date(dateParts[0]));
            activityInfo.setEndTime(new Date(dateParts[1]));
        }


        // 3. 提取展会logo
        String logoUrl = doc.selectFirst("div.tuan-pic-show img").attr("src");
        activityInfo.setPic(logoUrl);

        // 4. 提取展会地址
        String address = "";
        for (Element item : infoItems) {
            if (item.selectFirst("dt.tuan-name").text().equals("展会地点：")) {
                address = item.select("div.bao-key").text().trim();
                break;
            }
        }
        activityInfo.setAddress(address);

        // 5. 提取展会介绍
        String introduction = "";
        Element introSection = doc.selectFirst("div.ml4:has(p.zhxx:contains(展会介绍))");
        if (introSection != null) {
            Element introDiv = introSection.selectFirst("div.article.zhjs-1.zhjs_on");
            if (introDiv != null) {
                introduction = introDiv.text().trim();
            }
        }
        activityInfo.setDescription(introduction);
        activityInfo.setFirstActivityType("海外活动");
        activityInfo.setFirstActivityType("海外展会");
        activityInfo.setStartEnrollFlag(true);

        // 输出结果
        System.out.println("标题: " + title);
        System.out.println("开始时间: " + dateParts[0]);
        System.out.println("结束时间: " + dateParts[1]);
        System.out.println("Logo URL: " + logoUrl);
        System.out.println("地址: " + address);
        System.out.println("介绍: " + introduction);
        return activityInfo;
    }

    private String[] parseExhibitionDates(String dateText) {
        String[] dates = new String[2];
        Pattern pattern = Pattern.compile("(\\d{4})年(\\d{2})月(\\d{2})日[—\\-](\\d{2})月(\\d{2})日");
        Matcher matcher = pattern.matcher(dateText);

        if (matcher.find()) {
            String year = matcher.group(1);
            String startMonth = matcher.group(2);
            String startDay = matcher.group(3);
            String endMonth = matcher.group(4);
            String endDay = matcher.group(5);

            dates[0] = year + "-" + startMonth + "-" + startDay;
            dates[1] = year + "-" + endMonth + "-" + endDay;
        }
        return dates;
    }
}
